package group32.client;
import group32.shared.PhotoScore;
import group32.shared.Relation;
import group32.shared.Tuple;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.cobogw.gwt.user.client.ui.Rating;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.ext.linker.EmittedArtifact.Visibility;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.http.client.URL;
import com.google.gwt.http.client.UrlBuilder;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLTable;
import com.google.gwt.user.client.ui.HTMLTable.Cell;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.sun.org.apache.bcel.internal.generic.NEW;
import com.sun.org.apache.xerces.internal.util.URI;

public class Photo extends Composite{
	int userid=-1;
	
	private PhotoServiceAsync pService = GWT
	.create(PhotoService.class);
	
	private int userID;
	
	private int friendID=0;
	
	private int currentPhotoID=0;
	
	private Grid photoGrid;
	
	private Grid photoGrid2;
	
	private final static int photoCount = 1;
	
	private List<Tuple> currentPhotoTuples = new ArrayList<Tuple>();
	
	private List<Tuple> currentVisiblePhotoTuples = new ArrayList<Tuple>();
	
	private List<Tuple> currentCircleTuples;
	
	private List<Tuple> currentFriendTuples;
		
	private int currentPhoto=0;
	
	private boolean visib;
	
	private TextBox currentDescription = new TextBox();
	
	private Button next;
	
	private Button previous;
	
	private Button changeDescription;
	
	private TextBox tagArea = new TextBox();
	
	private Button addAtag;
	
	private Rating rw = new Rating(4,5);
	
	private Label lbScore = new Label();
	
	private HorizontalPanel photoPostedBy = new HorizontalPanel();
	


	//When a user wants to see it's photos or a sample of recommended photos.
	public Photo(final int userID, final String username, int photoType) {
		this.currentPhotoTuples.clear();
		this.currentVisiblePhotoTuples.clear();
		this.friendID=0;
		this.userID=0;

		//Get the current user
		this.userID=userID;
		System.out.println("UserID : " + this.userID);
		
		//Create the principal panel
		VerticalPanel principal = new VerticalPanel();
		principal.setSpacing(10);
		initWidget(principal);
		
		//Search page
		VerticalPanel dummy= new VerticalPanel();
		VerticalPanel searchPanel = new VerticalPanel();
		HorizontalPanel mainPanel= new HorizontalPanel();
		HorizontalPanel h1= new HorizontalPanel();
			VerticalPanel v1 = new VerticalPanel();
			VerticalPanel v2 = new VerticalPanel();
		HorizontalPanel h2= new HorizontalPanel();
		final TextBox searchField = new TextBox();
		Button bSearch= new Button();
		Anchor logOff = new Anchor();
		Anchor friends = new Anchor();
		Anchor circles = new Anchor();
		Anchor homepage = new Anchor();
		Anchor photos = new Anchor();
		VerticalPanel sp= new VerticalPanel();
		VerticalPanel sr= new VerticalPanel();
		searchPanel.setBorderWidth(1);
		searchPanel.setHeight("100px");
		searchPanel.setWidth("900px");
		searchPanel.add(dummy);
		dummy.setHeight("20px");
		bSearch.setText("Search");
		logOff.setText("LogOff");
		v1.setHorizontalAlignment(VerticalPanel.ALIGN_LEFT);
		v2.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
		v1.add(new HTML("Welcome "+username));v2.add(logOff);
		h2.add(v1);h2.add(v2);
		homepage.setText("Home");circles.setText("Circles");friends.setText("Friends");photos.setText("Photos");
		photos.setVisible(false);
		h1.add(homepage);h1.add(circles);h1.add(friends);h1.add(searchField);h1.add(bSearch);
		searchField.setWidth("350px");
		h1.setVerticalAlignment(HorizontalPanel.ALIGN_BOTTOM);
		h1.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT);
		searchPanel.add(h2);
		searchPanel.add(h1);
		logOff.addClickHandler(new ClickHandler() {
	        public void onClick(ClickEvent event) {
	            FlowControl.go(new Login());             
	        }           
	    });
		homepage.addClickHandler(new ClickHandler() {
	        public void onClick(ClickEvent event) {
	            FlowControl.go(new HomePage(userID, username));             
	        }           
	    });
		bSearch.addClickHandler(new ClickHandler() {
	        public void onClick(ClickEvent event) {
	        	if (!searchField.getValue().isEmpty()){
	            FlowControl.go(new Search(searchField.getValue(), userID));
	        	}
	        }           
	    });
		principal.add(searchPanel);
		
		
		//A dialogBox that will appear when clicking on add photo
		final DialogBox addingPhoto = new DialogBox();
		addingPhoto.setText("Adding a new photo");
		addingPhoto.setAnimationEnabled(true);
		VerticalPanel pp = new VerticalPanel();
		pp.setSpacing(10);
		HorizontalPanel hp4 = new HorizontalPanel();
		Label beforeUrl = new Label("Paste a url");
		final TextArea url = new TextArea();
		hp4.add(beforeUrl);
		hp4.add(url);
		pp.add(hp4);
		HorizontalPanel hp5 = new HorizontalPanel();
		Label beforeDescription = new Label("Description of the photo");
		final TextArea description = new TextArea();
		hp5.add(beforeDescription);
		hp5.add(description);
		pp.add(hp5);
		HorizontalPanel hp6 = new HorizontalPanel();
		final CheckBox visibility = new CheckBox("Visible to everyone");
		hp6.add(visibility);
		pp.add(hp6);
		HorizontalPanel hp7 = new HorizontalPanel();
		final ListBox circlesList = new ListBox();
		Button addcircle = new Button("add this circle");
	 	final ListBox circlesToAdd = new ListBox();
	 	final ArrayList<Integer> addingCircles=new ArrayList<Integer>();
		circlesToAdd.setVisibleItemCount(1);
		hp7.add(circlesList);
		hp7.add(addcircle);
		hp7.add(circlesToAdd);
		addcircle.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				if (circlesList.getItemCount()!=0){
					String cid = currentCircleTuples.get(circlesList.getSelectedIndex()).getValue("cid").toString();
					if (!addingCircles.contains(Integer.parseInt(cid))){
						addingCircles.add(Integer.parseInt(cid));
						circlesToAdd.addItem(circlesList.getItemText(circlesList.getSelectedIndex()));
						System.out.println("Circle added");
					}
				}
			}
			
		});
		pp.add(hp7);
		HorizontalPanel hp8 = new HorizontalPanel();
		final ListBox friendsList = new ListBox();
		Button addfriend = new Button("add this friend");
		final ListBox friendsToAdd = new ListBox();
		final ArrayList<Integer> addingFriends=new ArrayList<Integer>();
		friendsToAdd.setVisibleItemCount(1);
		hp8.add(friendsList);
		hp8.add(addfriend);
		hp8.add(friendsToAdd);
		addfriend.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				if (friendsList.getItemCount()!=0){
					String uid = currentFriendTuples.get(friendsList.getSelectedIndex()).getValue("userID").toString();
					if (!addingFriends.contains(Integer.parseInt(uid))){
						addingFriends.add(Integer.parseInt(uid));
						friendsToAdd.addItem(friendsList.getItemText(friendsList.getSelectedIndex()));
						System.out.println("Friend added");
					}
				}
			}
			
		});
		pp.add(hp8);
		
		Button confirm = new Button ("Ok");
		Button close = new Button("Close");
		HorizontalPanel addEnd = new HorizontalPanel();
		addEnd.add(confirm);
		addEnd.add(close);
		pp.add(addEnd);
		close.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				addingPhoto.hide();
				url.setText("");
				description.setText("");
				visibility.setValue(false);
				addingCircles.clear();
				addingFriends.clear();
				circlesToAdd.clear();
				friendsToAdd.clear();
			}		
		});
		confirm.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				String photoURL = url.getText();
				String realURL = URL.encode(photoURL);
				int everyone;
				if (!(realURL.equals(""))&&(realURL!=null)){
					if (visibility.getValue()){
						everyone=1;
					}
					else {
					everyone=0;	
					}
					insertPhoto(everyone, photoURL, description.getText(), addingCircles, addingFriends);
				}
				else {
					Window.alert("Put a valid URL");
				}
				getBackPhotos();
				addingPhoto.hide();
			}
			
		});
		
		addingPhoto.add(pp);
		
		
		
		
		//To change the description of the photo and add tags
		HorizontalPanel hp3 = new HorizontalPanel();
		changeDescription = new Button("Change description");
		addAtag = new Button("Add tag");
		hp3.add(currentDescription);
		hp3.add(changeDescription);
		principal.add(hp3);	
		changeDescription.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				if (currentDescription.getText()!=null){
					changeDesc();
					getBackPhotos();
				}
			}
			
		});
		addAtag.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				if (tagArea.getText()!=null){
					addTheTag(tagArea.getText());
					Window.alert("tag added !");
					tagArea.setText("");
				}
			}
			
		});
		
		// Set up the photo grid and the previous and next buttons and score
		HorizontalPanel reco = new HorizontalPanel();
		reco.add(new HTML("<div id='photoGridHeader'><h2>20 Best Photos<h2></div>"));
		photoGrid2 = new Grid(5,6);
		HorizontalPanel horizp2 = new HorizontalPanel();
		photoGrid2.setWidget(4, 5, horizp2);
		principal.add(reco);
		principal.add(photoGrid2);
		
		photoGrid2.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				Cell cell = photoGrid2.getCellForEvent(event);
				if (cell!=null){
					int selectedRow = cell.getRowIndex();
					int selectedColumn = cell.getCellIndex();
					System.out.println("Row:" + selectedRow);
					System.out.println("Column:" + selectedColumn);
					System.out.println("TotalPhotos :" +currentPhotoTuples.size());
					if (selectedColumn+5*selectedRow<20||selectedColumn+5*selectedRow<currentPhotoTuples.size()){
						int pID = Integer.parseInt(currentPhotoTuples.get(5*selectedRow+selectedColumn).getValue("photoID").toString());
						FlowControl.go(new Photo(userID,pID,Login.username,1));
					}				
				}
				
			}
		});
			
		photoGrid = new Grid(photoCount + 1, 1);
		HorizontalPanel horizp = new HorizontalPanel();
		photoGrid.setWidget(photoCount, 0, horizp);			
		principal.add(photoGrid);
		HorizontalPanel hp9 = new HorizontalPanel();
		HorizontalPanel hp10 = new HorizontalPanel();
		hp10.add(rw);
		hp10.add(lbScore);
		principal.add(hp10);
		hp9.add(tagArea);
		hp9.add(addAtag);
		principal.add(hp9);
		HorizontalPanel hp1 = new HorizontalPanel();				
		next = new Button("Next");
		next.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				currentPhoto++;
				photoView();
				getBackRating();
			}
			
		});
		previous = new Button("Previous");
		previous.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				currentPhoto--;
				photoView();
				getBackRating();
			}			
		});
		rw.addValueChangeHandler(new ValueChangeHandler<Integer>() {
			
			@Override
			public void onValueChange(ValueChangeEvent<Integer> event) {
				int score=event.getValue();
				rateThisPhoto(score);
				getBackRating();
			}
		});
		hp1.add(previous);
		hp1.add(next);
		principal.add(hp1);
		
		Button addPhoto = new Button("add a photo");
		hp1.add(addPhoto);
		addPhoto.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
					//We clear our lists and labels
					url.setText("");
					description.setText("");
					circlesList.clear();
					circlesToAdd.clear();
					visibility.setValue(false);
					addingCircles.clear();
					addingFriends.clear();
					circlesToAdd.clear();
					friendsToAdd.clear();
					//The popup appear
					addingPhoto.show();
					addingPhoto.center();
					
					//We fill the circle list box
					int sizeC = currentCircleTuples.size();
					for (int i=0; i<sizeC; i++){
						circlesList.addItem(currentCircleTuples.get(i).getValue("name").toString());
					}
					//We fill the friends list box
					int sizeF = currentFriendTuples.size();
					for (int i=0; i<sizeF; i++){
						friendsList.addItem(currentFriendTuples.get(i).getValue("firstname").toString() + " " + currentFriendTuples.get(i).getValue("lastname").toString());
					}
			}			
		});
		Button delete = new Button("Delete");
		hp1.add(delete);
		delete.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				supprPhoto();				
			}
		});
		
		//User profile page
		if (photoType==1){
			photoGrid.setVisible(true);
			searchPanel.setVisible(false);
			changeDescription.setVisible(true);
			addPhoto.setVisible(true);
			currentDescription.setReadOnly(false);
			addAtag.setVisible(false);
			tagArea.setVisible(false);
			photoGrid2.setVisible(false);
			rw.setReadOnly(false);
			rw.setVisible(false);
			lbScore.setVisible(false);
			next.setVisible(true);
			previous.setVisible(true);
			reco.setVisible(false);
			delete.setVisible(true);
		}
		else {
			//Tag mode
			if (photoType==2){
				System.out.println("TagMode");
				searchPanel.setVisible(false);
				changeDescription.setVisible(false);
				addPhoto.setVisible(false);
				currentDescription.setReadOnly(true);
				addAtag.setVisible(true);
				tagArea.setVisible(true);
				photoGrid2.setVisible(false);
				reco.setVisible(false);
				delete.setVisible(false);
			}
			else {
			currentDescription.setReadOnly(false);
			searchPanel.setVisible(true);
			changeDescription.setVisible(true);
			addPhoto.setVisible(true);
			addAtag.setVisible(false);
			tagArea.setVisible(false);
			rw.setVisible(true);
			photoGrid2.setVisible(false);
			reco.setVisible(false);
			delete.setVisible(false);
			}
		}	
		//For the homePage
		if (photoType==3){
			searchPanel.setVisible(false);
			photoGrid.setVisible(false);
			photoGrid2.setVisible(true);
			changeDescription.setVisible(false);
			addPhoto.setVisible(false);
			currentDescription.setVisible(false);
			currentDescription.setReadOnly(false);
			lbScore.setVisible(false);
			addAtag.setVisible(false);
			tagArea.setVisible(false);
			rw.setVisible(false);
			rw.setReadOnly(false);
			next.setVisible(false);
			previous.setVisible(false);
			reco.setVisible(true);			
			delete.setVisible(false);
			
			getBackPhotoSample();
			computeFriendsAndCircles();
		}
		else	{
			//We get back the photos and display them
			getBackPhotos();
			computeFriendsAndCircles();
		}
	}
	
	//When a user is viewing his friend's photos or when the user wants to see a photo in particular
	public Photo(final int userID, final int thingID , final String username, int type) {
		photoPostedBy.setVisible(false);
		this.currentPhotoTuples.clear();
		this.currentVisiblePhotoTuples.clear();
		this.friendID=0;
		this.userID=0;
		//Get the current user
		this.userID=userID;
		System.out.println("UserID : " + this.userID);
		
		//If we want to show the pictures of a friend
		if (type==0){
			this.friendID=thingID;
			System.out.println("friendID :"+ this.friendID);
		}
		
		//If we want to show a picture in particular
		if (type==1){
			this.currentPhotoID=thingID;
			photoPostedBy.setVisible(true);
		}
		
		//Create the principal panel
		VerticalPanel principal = new VerticalPanel();
		principal.setSpacing(10);
		initWidget(principal);
		
		//Search page
		VerticalPanel dummy= new VerticalPanel();
		VerticalPanel searchPanel = new VerticalPanel();
		HorizontalPanel mainPanel= new HorizontalPanel();
		HorizontalPanel h1= new HorizontalPanel();
			VerticalPanel v1 = new VerticalPanel();
			VerticalPanel v2 = new VerticalPanel();
		HorizontalPanel h2= new HorizontalPanel();
		final TextBox searchField = new TextBox();
		Button bSearch= new Button();
		Anchor logOff = new Anchor();
		Anchor friends = new Anchor();
		Anchor circles = new Anchor();
		Anchor homepage = new Anchor();
		Anchor photos = new Anchor();
		VerticalPanel sp= new VerticalPanel();
		VerticalPanel sr= new VerticalPanel();
		//searchPanel.setBorderWidth(1);
		searchPanel.setHeight("100px");
		searchPanel.setWidth("900px");
		searchPanel.add(dummy);
		dummy.setHeight("20px");
		bSearch.setText("Search");
		logOff.setText("LogOff");
		v1.setHorizontalAlignment(VerticalPanel.ALIGN_LEFT);
		v2.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
		v1.add(new HTML("Welcome "+username));v2.add(logOff);
		h2.add(v1);h2.add(v2);
		homepage.setText("Home");circles.setText("Circles");friends.setText("Friends");photos.setText("Photos");
		h1.add(homepage);h1.add(circles);h1.add(friends);h1.add(searchField);h1.add(bSearch);
		searchField.setWidth("350px");
		h1.setVerticalAlignment(HorizontalPanel.ALIGN_BOTTOM);
		h1.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT);
		searchPanel.add(h2);
		searchPanel.add(h1);
		logOff.addClickHandler(new ClickHandler() {
	        public void onClick(ClickEvent event) {
	            FlowControl.go(new Login());             
	        }           
	    });
		homepage.addClickHandler(new ClickHandler() {
	        public void onClick(ClickEvent event) {
	            FlowControl.go(new HomePage(userID, username));             
	        }           
	    });
		bSearch.addClickHandler(new ClickHandler() {
	        public void onClick(ClickEvent event) {
	        	if (!searchField.getValue().isEmpty()){
	            FlowControl.go(new Search(searchField.getValue(), userID));
	        	}
	        }           
	    });
		principal.add(searchPanel);
		
		principal.add(photoPostedBy);
		
		//To change the description of the photo
		HorizontalPanel hp3 = new HorizontalPanel();
		changeDescription = new Button("Change description");
		addAtag = new Button("Add tag");
		hp3.add(currentDescription);
		hp3.add(changeDescription);
		principal.add(hp3);
		changeDescription.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				if (currentDescription.getText()!=null){
					changeDesc();
					getBackPhotos();
				}
			}
			
		});
		addAtag.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				if (tagArea.getText()!=null){
					addTheTag(tagArea.getText());
					Window.alert("tag added !");
				}
			}
			
		});
		
		// Set up the photo grid and the previous and next buttons
		photoGrid = new Grid(photoCount + 1, 1);
		HorizontalPanel horizp = new HorizontalPanel();
		photoGrid.setWidget(photoCount, 0, horizp);
		principal.add(photoGrid);
		HorizontalPanel hp9 = new HorizontalPanel();
		HorizontalPanel hp10 = new HorizontalPanel();
		hp10.add(rw);
		hp10.add(lbScore);
		principal.add(hp10);
		hp9.add(tagArea);
		hp9.add(addAtag);
		principal.add(hp9);
		HorizontalPanel hp1 = new HorizontalPanel();				
		next = new Button("Next");
		next.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				currentPhoto++;
				photoView();
				getBackRating();
			}
			
		});
		previous = new Button("Previous");
		previous.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				currentPhoto--;
				photoView();
				getBackRating();
			}			
		});
		rw.addValueChangeHandler(new ValueChangeHandler<Integer>() {
			
			@Override
			public void onValueChange(ValueChangeEvent<Integer> event) {
				int score=event.getValue();
				rateThisPhoto(score);
				getBackRating();
			}
		});
		hp1.add(previous);
		hp1.add(next);
		principal.add(hp1);

		//Tag mode
		searchPanel.setVisible(false);
		changeDescription.setVisible(false);
		currentDescription.setReadOnly(true);
		addAtag.setVisible(true);
		tagArea.setVisible(true);
		
		if (type==1){//We are only showing one photo, then there is no need to show the previous and next buttons
			searchPanel.setVisible(true);
			previous.setVisible(false);
			next.setVisible(false);
			getBackPhoto();
		}
		else {
			getBackPhotos();
		}
		//We get back the photos and display them		
		computeFriendsAndCircles();	
	}
	
	public void getBackPhoto(){
		pService.getPhoto(currentPhotoID ,new AsyncCallback<Relation>() {
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("This photo doesn't exist");				
			}
			@Override
			public void onSuccess(Relation result) {
				System.out.println(userID);
				currentPhotoTuples=result.getTableAsList();
				String name = currentPhotoTuples.get(currentPhoto).getValue("firstname").toString()+ " " +currentPhotoTuples.get(currentPhoto).getValue("lastname");
				photoPostedBy.add(new HTML("<div id='photoGridHeader'><h2>Photo posted by "+name+ " <h2></div>"));
				photoView();
				getBackRating();
			}			
		});
	}
	
	public void getBackPhotos(){
		pService.getUserPhotos(userID ,new AsyncCallback<Relation>() {
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Unable to find photos");				
			}
			@Override
			public void onSuccess(Relation result) {
				System.out.println(userID);
				currentPhotoTuples=result.getTableAsList();
				//If we only want to show the photos visible by a friend
				if (friendID!=0){
					final int size = currentPhotoTuples.size();
					System.out.println("FriendID"+friendID);
					for (int i=0;i<size;i++){
						final int currentIndex = i;
						pService.isVisible(friendID,Integer.parseInt(currentPhotoTuples.get(i).getValue("photoID").toString()), new AsyncCallback<Boolean>() {
							@Override
							public void onFailure(Throwable caught) {
								Window.alert("");
							}
							public void onSuccess(Boolean result) {
								visib=result;
								if (visib==true){
									currentVisiblePhotoTuples.add(currentPhotoTuples.get(currentIndex));
								}
								if (currentIndex==(size-1)){
									//If we have checked all the photos, we display the visible ones
									photoView();
									getBackRating();
								}
							}
						});
					}
				}
				else {
				photoView();
				getBackRating();
				}
			}			
		});
	}
	
	public void getBackPhotoSample(){
		pService.getPhotoSample(userID ,new AsyncCallback<Relation>() {
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Unable to find photos");				
			}
			@Override
			public void onSuccess(Relation result) {
				System.out.println(userID);
				//We get back a sample and we rate each photo
				final List<Tuple> temporaryList = result.getTableAsList();
				System.out.println("TemporaryList Size :"+temporaryList.size());
				final ArrayList<PhotoScore> S = new ArrayList<PhotoScore>();
				for (int i=0;i<temporaryList.size();i++){
					int id = Integer.parseInt(temporaryList.get(i).getValue("photoID").toString());
					final int counter=i;
					pService.scorePhoto(userID, id, new AsyncCallback<Float>(){
							@Override
							public void onFailure(Throwable caught) {
								Window.alert("");
							}
							public void onSuccess(Float result) {
								//The more recent the photo is, the best score it has
								float res = Math.max((result - counter/20),0);
								S.add(new PhotoScore(counter,res));
								if (S.size()==temporaryList.size()){
									Collections.sort(S);
									int n = S.size();
									for (int i=n-1;i>-1;i--){
										Tuple toAdd = temporaryList.get(S.get(i).getIndex());
										currentPhotoTuples.add(toAdd);
									}
									photoView();
									getBackRating();
								}
							}
							
						});											
					}
			}			
		});
	}
	
	public void photoView(){
		//If we want to display the photos visible from a friend
		if (friendID!=0){
			//If there is something to show
			if (currentVisiblePhotoTuples.size()!=0)  {								
				int size = currentVisiblePhotoTuples.size();
				String address="";
				if (currentPhoto==size){
					currentPhoto=0;
				}
				if (currentPhoto<0){
					currentPhoto=size-1;
				}
				address=currentVisiblePhotoTuples.get(currentPhoto).getValue("url").toString();
				photoGrid.setHTML(0, 0, "<img src='" + address + "' style='max-height:250px; max-width:300px'/>");
				System.out.println(currentVisiblePhotoTuples.get(currentPhoto).getValue("photoID").toString());
				currentDescription.setText(currentVisiblePhotoTuples.get(currentPhoto).getValue("description").toString());	
				}
			//Else, do not show anything
			else {
				next.setVisible(false);
				previous.setVisible(false);
				currentDescription.setVisible(false);
				changeDescription.setVisible(false);
				tagArea.setVisible(false);
				addAtag.setVisible(false);
				rw.setVisible(false);
				lbScore.setVisible(false);
			}
		}
		else {//We want to show the photos of the user
			//If there is something to show
			if (currentPhotoTuples.size()!=0)  {									
				int size = currentPhotoTuples.size();
				String address="";
				if (currentPhoto==size){
					currentPhoto=0;
				}
				if (currentPhoto<0){
					currentPhoto=size-1;
				}
				address=currentPhotoTuples.get(currentPhoto).getValue("url").toString();
				photoGrid.setHTML(0, 0, "<img src='" + address + "' style='max-height:250px; max-width:300px'/>");
				System.out.println(currentPhotoTuples.get(currentPhoto).getValue("photoID").toString());
				currentDescription.setText(currentPhotoTuples.get(currentPhoto).getValue("description").toString());
				
				if (photoGrid2!=null){
					for (int i=0;i<size&&i<20;i++){
						if (i<5){
							address = currentPhotoTuples.get(i).getValue("url").toString();
							photoGrid2.setHTML(0, i, "<img src='" + address + "' style='max-height:50px; max-width:50px'/>");
						}
						else {
							if (i<10){
								address = currentPhotoTuples.get(i).getValue("url").toString();
								photoGrid2.setHTML(1, i-5, "<img src='" + address + "' style='max-height:50px; max-width:50px'/>");
							}
							else {
								if (i<15) {
									address = currentPhotoTuples.get(i).getValue("url").toString();
									photoGrid2.setHTML(2, i-10, "<img src='" + address + "' style='max-height:50px; max-width:50px'/>");
								}
								else {
									address = currentPhotoTuples.get(i).getValue("url").toString();
									photoGrid2.setHTML(3, i-15, "<img src='" + address + "' style='max-height:50px; max-width:50px'/>");
								}
							}
						}
					}
				}
			}
			else {
				//Else, do not show anything 
				next.setVisible(false);
				previous.setVisible(false);
				currentDescription.setVisible(false);
				changeDescription.setVisible(false);
				tagArea.setVisible(false);
				addAtag.setVisible(false);
				rw.setVisible(false);
				lbScore.setVisible(false);
			}
		}
	}
	
	@SuppressWarnings("rawtypes")
	public void changeDesc(){
		pService.changeDescription(currentPhotoTuples.get(currentPhoto).getValue("photoID").toString(), currentDescription.getText() ,new AsyncCallback() {
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("");				
			}
			@Override
			public void onSuccess(Object result) {
				System.out.println("New description added for photo:"+currentPhotoTuples.get(currentPhoto).getValue("photoID").toString());
				
			}		
		});
	}
	
	public void computeFriendsAndCircles(){
		pService.getUserCircles(userID, new AsyncCallback<Relation>(){
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Unable to find circles");				
			}
			@Override
			public void onSuccess(Relation result) {
				System.out.println(userID);
				currentCircleTuples=result.getTableAsList();
			}			
		});
		pService.getUserFriends(userID, new AsyncCallback<Relation>(){
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Unable to find friends");				
			}
			@Override
			public void onSuccess(Relation result) {
				System.out.println(userID);
				currentFriendTuples=result.getTableAsList();
			}			
		});
	}
	
	@SuppressWarnings("rawtypes")
	public void insertPhoto(int everyone, String url, String description, ArrayList<Integer> circles, ArrayList<Integer> friends){
		pService.addPhoto(userID, url, description, everyone, circles, friends, new AsyncCallback(){
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Unable to update");				
			}
			@Override
			public void onSuccess(Object result) {
				// TODO Auto-generated method stub				
			}			
		});
	}
	
	@SuppressWarnings("rawtypes")
	public void addTheTag(String tag){
		if (friendID==0){
			int pID=Integer.parseInt(currentPhotoTuples.get(currentPhoto).getValue("photoID").toString());
			pService.addTag(tag, pID, userID, new AsyncCallback(){
				@Override
				public void onFailure(Throwable caught) {
					Window.alert("");				
				}
				@Override
				public void onSuccess(Object result) {
					System.out.println("New tag added for photo:"+currentPhotoTuples.get(currentPhoto).getValue("photoID").toString());				
				}		
			});
		}
		else {
			int pID=Integer.parseInt(currentPhotoTuples.get(currentPhoto).getValue("photoID").toString());
			pService.addTag(tag, pID, friendID, new AsyncCallback(){
				@Override
				public void onFailure(Throwable caught) {
					Window.alert("");				
				}
				@Override
				public void onSuccess(Object result) {
					System.out.println("New tag added for photo:"+currentPhotoTuples.get(currentPhoto).getValue("photoID").toString());				
				}		
			});
		}
	}
	
	public boolean isVis (int photoID){
		pService.isVisible(friendID, photoID, new AsyncCallback<Boolean>(){
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("");
			}
			public void onSuccess(Boolean result) {
				visib=result;
				System.out.println("this photo is visible");
			}		
		});
		return visib;
	}
	
	@SuppressWarnings("rawtypes")
	public void rateThisPhoto (int scoreGiven) {
		if (friendID!=0){//Means that a friend is rating a photo of the user
			int pID=Integer.parseInt(currentVisiblePhotoTuples.get(currentPhoto).getValue("photoID").toString());
			pService.ratePhoto(friendID, pID, scoreGiven, new AsyncCallback(){
				@Override
				public void onFailure(Throwable caught) {				
				}
				@Override
				public void onSuccess(Object result) {
					System.out.println("New rate added for photo:"+currentVisiblePhotoTuples.get(currentPhoto).getValue("photoID").toString());				
				}		
			});
		}
		else {//The user is rating one of the recommended photos
			int pID=Integer.parseInt(currentPhotoTuples.get(currentPhoto).getValue("photoID").toString());
			pService.ratePhoto(userID, pID, scoreGiven, new AsyncCallback(){
				@Override
				public void onFailure(Throwable caught) {			
				}
				@Override
				public void onSuccess(Object result) {
					System.out.println("New rate added for photo:"+currentPhotoTuples.get(currentPhoto).getValue("photoID").toString());				
				}		
			});
		}
	}
	
	public void getBackRating(){
		if (friendID!=0){//If a friend is visualizing the photos of the user
			pService.getPhotoAvgRating(Integer.parseInt(currentVisiblePhotoTuples.get(currentPhoto).getValue("photoID").toString()), new AsyncCallback<Float>(){
				@Override
				public void onFailure(Throwable caught) {
					Window.alert("");				
				}
				@Override
				public void onSuccess(Float result) {
					lbScore.setText(result.toString());
					float preRes=result;
					rw.setValue((int) preRes, false);
				}		
			});
		}
		else {//If the user is visualizing it's own photos or the recommended photos
			pService.getPhotoAvgRating(Integer.parseInt(currentPhotoTuples.get(currentPhoto).getValue("photoID").toString()), new AsyncCallback<Float>(){
				@Override
				public void onFailure(Throwable caught) {
					Window.alert("");				
				}
				@Override
				public void onSuccess(Float result) {
					lbScore.setText(result.toString());
					float preRes=result;
					rw.setValue((int) preRes, false);
				}		
			});
		}
	}
	
	public void supprPhoto() {
		int pID = Integer.parseInt(currentPhotoTuples.get(currentPhoto).getValue("photoID").toString());
		pService.deletePhoto(userID, pID, new AsyncCallback(){
			@Override
			public void onFailure(Throwable caught) {			
			}
			@Override
			public void onSuccess(Object result) {
				getBackPhotos();				
			}
		});
	}
}
